/////////////////////////////////////////////////////////////////////////////
// Original code from libhdfs3. Copyright (c) 2013 - 2014, Pivotal Inc.
// All rights reserved. Author: Zhanwei Wang
/////////////////////////////////////////////////////////////////////////////
//  Modifications by Kumo Inc.
// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//



#include <kmhdfs/client/directory_iterator.h>
#include <kmhdfs/client/file_status.h>
#include <kmhdfs/common/exception.h>
#include <kmhdfs/common/exception_internal.h>
#include <kmhdfs/client/file_system_impl.h>

namespace Hdfs {

DirectoryIterator::DirectoryIterator() :
    needLocations(false), filesystem(NULL), next(0) {
}

DirectoryIterator::DirectoryIterator(Hdfs::Internal::FileSystemImpl * const fs,
                                     std::string path, bool needLocations) :
    needLocations(needLocations), filesystem(fs), next(0), path(path) {
}

DirectoryIterator::DirectoryIterator(const DirectoryIterator & it) :
    needLocations(it.needLocations), filesystem(it.filesystem), next(it.next), path(it.path), startAfter(
        it.startAfter), lists(it.lists) {
}

DirectoryIterator & DirectoryIterator::operator =(const DirectoryIterator & it) {
    if (this == &it) {
        return *this;
    }

    needLocations = it.needLocations;
    filesystem = it.filesystem;
    next = it.next;
    path = it.path;
    startAfter = it.startAfter;
    lists = it.lists;
    return *this;
}

bool DirectoryIterator::getListing() {
    bool more;

    if (NULL == filesystem) {
        return false;
    }

    next = 0;
    lists.clear();
    more = filesystem->getListing(path, startAfter, needLocations, lists);

    if (!lists.empty()) {
        startAfter = lists.back().getPath();
    }

    return more || !lists.empty();
}

bool DirectoryIterator::hasNext() {
    if (next >= lists.size()) {
        return getListing();
    }

    return true;
}

Hdfs::FileStatus DirectoryIterator::getNext() {
    if (next >= lists.size()) {
        if (!getListing()) {
            THROW(HdfsIOException, "End of the dir flow");
        }
    }

    return lists[next++];
}

}
